﻿#include "ff.h"
#include "ebook_api.h"
#include "ebook_init.h"
#include "ebook_util.h"
#include "db_format.h"

EBOOK_CONTENT * hebook = 0;

int init_text()
{
	int res;
	res = ffopen(&hebook->f_txt, hebook->fname, FA_READ);
	if(res != FR_OK)
	{
		return res;
	}

	//获取txt文件信息，编码格式、文件大小等
	res = get_txt_info();
	if(res != FR_OK)
	{
		ffclose(&hebook->f_txt);
		return res;
	}

	return FR_OK;
}

int check_index(char * fname)
{
	//return 0:	//索引文件不存在，创建线程构建索引
	//return 1:	//索引文件存在，并且完好
	//return 2:	//索引文件存在，但是不完整，创建线程完善索引
	//return 3:	//索引文件存在，但是和txt文件不匹配，删除索引文件，并创建线程构建索引
	
	int res;
	FIL * f = 0;
	INDEX_HEAD head;
	unsigned br = 0;
	long long last;
	int offset;
	res = ffopen(&f, fname, FA_READ);
	if(res != FR_OK)
	{
		return 0;
	}

	res = f_read(f, &head, sizeof(INDEX_HEAD), &br);
	if(res != FR_OK)
	{
		ffclose(&f);
		return 3;
	}
	
	if(br != sizeof(INDEX_HEAD))
	{
		ffclose(&f);
		return 3;
	}

	if(head.version != EBOOK_VERSION)
	{
		ffclose(&f);
		return 4;
	}

	if( fnamecmp(head.fname, hebook->fname) != 0 ||
		head.format != hebook->format ||
		head.f_size != hebook->f_size )
	{
		ffclose(&f);
		return 3;
	}

	last = f_size(f);
	last -= sizeof(int);
	if(sizeof(INDEX_HEAD) + head.pages*sizeof(int) != last)
	{
		ffclose(&f);
		return 3;
	}

	f_lseek(f, last); 
	res = f_read(f, &offset, sizeof(int), &br);
	if(res != FR_OK)
	{
		ffclose(&f);
		return 3;
	}
	if(br != sizeof(int))
	{
		ffclose(&f);
		return 3;
	}

	if(head.building == 1)
	{
		ffclose(&f);
		return 2;
	}

	else if(head.building == -1)
	{
		ffclose(&f);
		return 3;
	}
	
	else if(head.building == 0 && offset != hebook->f_size)
	{
		ffclose(&f);
		return 3;
	}

	ffclose(&f);
	return 1;
}

int init_index1(char * fname)//索引文件存在，并且完好
{
	int res;
	unsigned br = 0;

	res = ffopen(&hebook->f_idx, fname, FA_READ|FA_WRITE);
	if(res != FR_OK)
	{
		return res;
	}

	res = f_read(hebook->f_idx, hebook, sizeof(INDEX_HEAD), &br);
	if(res != FR_OK)
	{
		ffclose(&hebook->f_idx);
		return res;
	}
	if(br != sizeof(INDEX_HEAD))
	{
		ffclose(&hebook->f_idx);
		return res;
	}

	hebook->q_to_task = (void*)0;
	hebook->q_fm_task = (void*)0;
	hebook->task = (void*)0;

	return FR_OK;
}

int init_index2(char * fname)//索引文件存在，但是不完整，创建线程完善索引
{
	int res;
	unsigned br = 0;
	res = ffopen(&hebook->f_idx, fname, FA_READ|FA_WRITE);
	if(res != FR_OK)
	{
		return res;
	}

	res = f_read(hebook->f_idx, hebook, sizeof(INDEX_HEAD), &br);
	if(res != FR_OK)
	{
		ffclose(&hebook->f_idx);
		return res;
	}
	if(br != sizeof(INDEX_HEAD))
	{
		ffclose(&hebook->f_idx);
		return res;
	}

	res = create_task();
	if(res != FR_OK)
	{
		ffclose(&hebook->f_idx);
		return res;
	}

	return FR_OK;
}

int init_index0(char * fname)//索引文件不存在，创建线程构建索引
{
	int res;
	unsigned br = 0;
	int offset[2] = {0,0};

	res = ffopen(&hebook->f_idx, fname, FA_READ|FA_WRITE|FA_CREATE_ALWAYS);
	if(res != FR_OK)
	{
		return res;
	}

	hebook->building = 1;
	hebook->page = 0;
	hebook->pages = 1;

	switch(hebook->format)
	{
	case ASCII_FORMAT:
	case ANSI_FORMAT:
	case UTF_8_NOBOM_FORMAT:
		offset[0] = 0;
		break;

	case UTF_8_BOM_FORMAT:
		offset[0] = 3;
		break;

	case UTF_16_L_ENDIAN_FORMAT:
	case UTF_16_B_ENDIAN_FORMAT:
	case UTF_32_L_ENDIAN_FORMAT:
	case UTF_32_B_ENDIAN_FORMAT:
		offset[0] = 2;
		break;
	default:
		assert(0);
	}
	
	res = calculate_page_offset(offset);
	switch(res)
	{
	case 0:		//构建索引文件单步OK
		break;

	case -1:	//构建索引文件出错
	case -2:	//txt文件结束，本次单步无数据
		ffclose(&hebook->f_idx);
		return res;

	default:
		//assert(0);	//not arrived
		break;
	}

	res = f_write(hebook->f_idx, hebook, sizeof(INDEX_HEAD), &br);
	if(res != FR_OK)
	{
		ffclose(&hebook->f_idx);
		return res;
	}
	res = f_write(hebook->f_idx, offset, sizeof(offset), &br);
	if(res != FR_OK)
	{
		ffclose(&hebook->f_idx);
		return res;
	}
	ffclose(&hebook->f_idx);

	return init_index2(fname);
}

int init_index3(char * fname)//索引文件存在，但是和txt文件不匹配，删除索引文件，并创建线程构建索引
{
	return init_index0(fname);
}

int init_index4(char * fname)//索引文件存在，但是和txt文件不匹配，删除索引文件，并创建线程构建索引
{
	return init_index0(fname);
}

int init_index()
{
	int res;

	res = check_index(hebook->fidx);

	switch(res)
	{
	case 0:	//索引文件不存在，创建线程构建索引
		res = init_index0(hebook->fidx);
		break;
	case 1:	//索引文件存在，并且完好
		res = init_index1(hebook->fidx);
		break;
	case 2:	//索引文件存在，但是不完整，创建线程完善索引
		res = init_index2(hebook->fidx);
		break;
	case 3:	//索引文件存在，但是和txt文件不匹配，删除索引文件，并创建线程构建索引
		res = init_index3(hebook->fidx);
		break;
	case 4:	//版本不匹配，删除索引文件，并创建线程构建索引
		res = init_index4(hebook->fidx);
		break;
	default:
		//assert(0); //not arrived
		res = -1;
		break;
	}

	return res;
}

int init_()
{
	int res;

	res = init_text();
	if(res != FR_OK)
	{
		return res;
	}

	res = init_index();
	if(res != FR_OK)
	{
		ffclose(&hebook->f_txt);
		return res;
	}

	return 0;
}
